using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEngine;

namespace Mars.ShaderAnalysis
{
    [Serializable]
    public class PassAnalysis
    {
        [NonSerialized] public bool isFoldOut = true;
        [NonSerialized] public bool isKeywordSelectFoldOut = false;
        [NonSerialized] public bool isAnalysisFoldOut = true;
        [NonSerialized] public CompileVariantAnalysis frameCompileVariantAnalysis = new CompileVariantAnalysis();
        [NonSerialized] public CompileVariantAnalysis vertexCompileVariantAnalysis = new CompileVariantAnalysis();
        public string lightMode = "Unnamed";
        public string passName = "Unnamed";
        public List<ShaderKeywordsState> keywordsStateList = new List<ShaderKeywordsState>();
        private bool hasAnalysis = false;

        public PassAnalysis()
        {
        }

        public PassAnalysis(PassAnalysis passAnalysis)
        {
            DeepCopy(passAnalysis);
        }

        public void DeepCopy(PassAnalysis passAnalysis)
        {
            //只深拷贝序列化属性
            lightMode = passAnalysis.lightMode;
            passName = passAnalysis.passName;
            for (int i = 0; i < passAnalysis.keywordsStateList.Count; i++)
            {
                keywordsStateList.Add(new ShaderKeywordsState(passAnalysis.keywordsStateList[i]));
            }

            hasAnalysis = false;
        }

        /// <summary>
        /// 获取顶点组合数
        /// </summary>
        public ulong GetVertexCombinesCount()
        {
            ulong count = 1;
            for (int i = 0; i < keywordsStateList.Count; i++)
            {
                ShaderKeywordsState shaderKeywordsState = keywordsStateList[i];
                if (shaderKeywordsState.isOpen && shaderKeywordsState.hasVertex)
                {
                    count *= (ulong)shaderKeywordsState.keywords.Count;
                }
            }

            return count;
        }

        /// <summary>
        /// 获取片元组合数
        /// </summary>
        public ulong GetFragmentCombinesCount()
        {
            ulong count = 1;
            for (int i = 0; i < keywordsStateList.Count; i++)
            {
                ShaderKeywordsState shaderKeywordsState = keywordsStateList[i];
                if (shaderKeywordsState.isOpen && shaderKeywordsState.hasFragment)
                {
                    count *= (ulong)shaderKeywordsState.keywords.Count;
                }
            }

            return count;
        }

        /// <summary>
        /// 分析数据
        /// </summary>
        /// <param name="force"></param>
        public void Analysis(bool force = false)
        {
            if (!force && hasAnalysis)
            {
                return;
            }

            for (int i = 0; i < keywordsStateList.Count; i++)
            {
                keywordsStateList[i].Analysis();
            }

            hasAnalysis = true;
        }

        /// <summary>
        /// 变体组合是否可用
        /// </summary>
        public bool IsKeywordsAvailable(string[] keywords)
        {
            //空组合必定可用
            if (keywords == null || keywords.Length <= 0)
            {
                return true;
            }

            //分析一次数据
            Analysis();
            //遍历keyword，是否存在非法的
            for (int i = 0; i < keywords.Length; i++)
            {
                string keyword = keywords[i];
                bool isExist = false;
                //遍历所有已开启的Keyword，是否存在
                for (int j = 0; j < keywordsStateList.Count; j++)
                {
                    ShaderKeywordsState state = keywordsStateList[j];
                    if (state.isOpen && state.keywords != null)
                    {
                        for (int k = 0; k < state.keywords.Count; k++)
                        {
                            if (keyword == state.keywords[k])
                            {
                                isExist = true;
                                break;
                            }
                        }
                    }
                }

                //有一个不存在，则整个变体组合不可用
                if (!isExist)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 编译并显示Pass
        /// </summary>
        public void CompileVariantAndAnalysis(Shader shader, int subShaderIndex, int passIndex, ShaderCompilerPlatform shaderCompilerPlatform, BuildTarget buildTarget)
        {
            //收集选中的keyword字符串
            List<string> currentKeywords = GetSelectedKeywordList();
            //分析
            vertexCompileVariantAnalysis.SetData(shader, subShaderIndex, passIndex, currentKeywords.ToArray(), ShaderType.Vertex, shaderCompilerPlatform, buildTarget);
            vertexCompileVariantAnalysis.Execute();
            frameCompileVariantAnalysis.SetData(shader, subShaderIndex, passIndex, currentKeywords.ToArray(), ShaderType.Fragment, shaderCompilerPlatform, buildTarget);
            frameCompileVariantAnalysis.Execute();
        }

        /// <summary>
        /// 获取选中的keyword列表
        /// </summary>
        public List<string> GetSelectedKeywordList()
        {
            //收集选中的keyword字符串
            List<string> currentKeywords = new List<string>();
            for (int k = 0; k < keywordsStateList.Count; k++)
            {
                ShaderKeywordsState shaderKeywordsState = keywordsStateList[k];
                string keyword = shaderKeywordsState.keywords[shaderKeywordsState.selectKeywordIndex];
                if (shaderKeywordsState.isOpen && !string.IsNullOrEmpty(keyword))
                {
                    currentKeywords.Add(keyword);
                }
            }

            //排序
            currentKeywords.Sort(KeywordCompare);
            return currentKeywords;
        }

        /// <summary>
        /// Keyword比较
        /// </summary>
        private static int KeywordCompare(string a, string b)
        {
            return string.Compare(a, b, StringComparison.Ordinal);
        }
    }
}